#include "StatusServiceImplement.h"
#include "ConfigManager.h"
#include "RedisManager.h"

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>


StatusServiceImplement::StatusServiceImplement()
{
	auto& cfg = ConfigManager::getInstance();
	auto server_list = cfg["chatservers"]["Name"];

	std::vector<std::string> words;

	std::stringstream ss(server_list);
	std::string word;

	while (std::getline(ss, word, ',')) {
		words.push_back(word);
	}
	
	for (auto& word : words) {
		if (cfg[word]["Name"].empty()) {
			continue;
		}

		ChatServer server;
		server.port = cfg[word]["Port"];
		server.host = cfg[word]["Host"];
		server.name = cfg[word]["Name"];
		m_servers[server.name] = server;
	}
}

grpc::Status StatusServiceImplement::GetChatServer(grpc::ServerContext* context, const message::GetChatServerReq* request, message::GetChatServerRsp* reply)
{
	std::string prefix("xiao status server has received :  ");
	const auto& server = getChatServer();
	reply->set_host(server.host);
	reply->set_port(server.port);
	reply->set_error(ErrorCodes::Success);
	reply->set_token(generate_unique_string());
	insertToken(request->uid(), reply->token());

	return grpc::Status::OK;
}

grpc::Status StatusServiceImplement::Login(grpc::ServerContext* context, const message::LoginReq* request, message::LoginRsp* reply)
{
	auto uid = request->uid();
	auto token = request->token();

	// 从redis中获取token
	std::string uid_str = std::to_string(uid);
	std::string token_key = USERTOKENPREFIX + uid_str;
	std::string token_value = "";
	bool res = RedisManager::getInstance()->get(token_key, token_value);
	if (!res) {
		reply->set_error(ErrorCodes::TokenInvalid);
		return grpc::Status::OK;
	}

	if (token_value != token) {
		reply->set_error(ErrorCodes::TokenInvalid);
		return grpc::Status::OK;
	}

	reply->set_error(ErrorCodes::Success);
	reply->set_uid(uid);
	reply->set_token(token);
	return grpc::Status::OK;
}

// 向redis中插入token
void StatusServiceImplement::insertToken(int uid, std::string token)
{
	std::string uid_str = std::to_string(uid);
	std::string token_key = USERTOKENPREFIX + uid_str;
	RedisManager::getInstance()->set(token_key, token);
}

std::string StatusServiceImplement::generate_unique_string()
{
	boost::uuids::uuid uuid = boost::uuids::random_generator()();

	std::string unique_string = boost::uuids::to_string(uuid);

	return unique_string;
}

// Todo: 优化算法，选取最少连接数的服务器
ChatServer StatusServiceImplement::getChatServer()
{
	std::lock_guard<std::mutex> lock(m_server_mtx);
	auto minServer = m_servers.begin()->second;
	auto count_str = RedisManager::getInstance()->hGet(LOGIN_COUNT, minServer.name);
	// 未找到，则默认设置为最大连接数(服务器可能未启动)
	if (count_str.empty()) {
		minServer.con_count = INT_MAX;
	}
	else {
		minServer.con_count = std::stoi(count_str);
	}

	// 取出最小连接数的ChatServer
	for (auto& server : m_servers) {
		if (server.second.name == minServer.name) {
			continue;
		}

		auto count_str = RedisManager::getInstance()->hGet(LOGIN_COUNT, server.second.name);
		if (count_str.empty()) {
			server.second.con_count = INT_MAX;
		}
		else {
			server.second.con_count = std::stoi(count_str);
		}

		if (server.second.con_count < minServer.con_count) {
			minServer = server.second;
		}
	}

	return minServer;
}
